#include <cstdio>
#include <queue>

using namespace std;

#define INF 0x3F3F3F3F
#define MAXN 100+5

struct edge {
    int u, v, c;
    bool operator < (const edge & rhs) const {
        return c > rhs.c;
    }
};

int N, Q;
priority_queue<edge> que;
int FL[MAXN];

int main()
{
    scanf("%d", &N);
    for (int i=1; i<=N; i++) {
        for (int j=1; j<=N; j++) {
            int c;
            scanf("%d", &c);
            if (c == 0) c = INF;
            que.push(edge{i, j, c});
        }
    }
    scanf("%d", &Q);
    for (int i=1; i<=N; i++) {
        FL[i] = i;
    }
    for (int i=1; i<=Q; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        int flu = FL[u], flv = FL[v];
        for (int j=1; j<=N; j++) {
            if (FL[j] == flv)
                FL[j] = flu;
        }
    }
    //Kruskal
    int ans = 0;
    while (!que.empty()) {
        edge e = que.top(); que.pop();
        if (FL[e.u] == FL[e.v]) continue;
        ans += e.c;
        int flu = FL[e.u], flv = FL[e.v];
        bool flag = true;
        for (int i=1; i<=N; i++) {
            if (FL[i] == flv)
                FL[i] = flu;
            if (i>1) {
                if (FL[i-1] != FL[i])
                    flag = false;
            }
        }
        if (flag) break;
    }
    printf("%d\n", ans);
    return 0;
}
